package com.dy.springcloud.controller;

import com.alibaba.csp.sentinel.annotation.SentinelResource;
import com.alibaba.csp.sentinel.slots.block.BlockException;
import com.dy.springcloud.handler.CustomGlobalBlockHandler;
import com.dy.springcloud.handler.CustomGlobalFallbackHandler;
import com.dy.springcloud.service.MemberService;
import com.dy.springcloud.entity.Member;
import com.dy.springcloud.entity.Result;

import lombok.extern.slf4j.Slf4j;
import org.springframework.web.bind.annotation.*;

import javax.annotation.Resource;
import java.util.Date;
import java.util.concurrent.TimeUnit;

@RestController
@Slf4j
public class MemberController {
    @Resource
    private MemberService memberService;

    //流量控制 关联 测试接口
    @GetMapping("/t1")
    public Result t1(){
        return Result.success("t1成功 nacos 10004");
    }
    @GetMapping("/t2")
    public Result t2(){
        //让线程休眠 1s, 模拟执行时间
        try {
            TimeUnit.MILLISECONDS.sleep(1000);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
        log.info("t2 当 前 线 程 id={}" , Thread.currentThread().getId());

        return Result.success("t2成功 nacos 10004");
    }
    @GetMapping("/t3")
    public Result t3(){
        //让线程休眠 1s, 模拟执行时间
        try {
            TimeUnit.MILLISECONDS.sleep(300);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }

        return Result.success("t2成功 nacos 10004");
    }
    private static int num = 0;
    @GetMapping(value = "/t4")
    public Result t4() {
        if ((++num) % 2 == 0) {//异常比例 50%
            System.out.println(3 / 0);
        }
        log.info(" 熔 断 降 级 测 试 【 异 常 比 例 】 执 行 t4() 线 程 id= " +
                Thread.currentThread().getId());
        return Result.success("t4()执行");
    }
    @GetMapping(value = "/t5")
    public Result t5() {
        if ((++num) <= 10) {//异常比例 50%
            System.out.println(3 / 0);
        }
        return Result.success("t5()执行");
    }
    //热点key限流测试
    //自定义一个热点限流处理方法
    public Result newBlockHandler(String id, String type, BlockException blockException) {
        return Result.success("触发"+id+"热点key限流保护");
    }
    //在sentinel中设置对方法的id参数进行热点限流
    @GetMapping("/news")
    //@SentinelResource指定sentinel限流资源，value = "news"设置在sentinel显示的资源名，
    //blockHandler = "newBlockHandler" 设置热点限流处理方法
    @SentinelResource(value = "news",blockHandler = "newBlockHandler")
    public Result news(@RequestParam("id")String id,@RequestParam("type")String type){
        return Result.success("查询"+id+"新闻");
    }
    //全局处理类
    @GetMapping(value = "/t6")
    @SentinelResource(
            //sentinel设置时，需要对资源t6设置，不是/t6
            value = "t6",
            //blockHandlerClass 指定全局限流处理类， blockHandler指定 使用类中哪个方法处理限流异常
            //blockHandlerMethod1方法需要有t6()的参数，并且顺序匹配
            blockHandlerClass = CustomGlobalBlockHandler.class, blockHandler = "blockHandlerMethod1",
            //fallbackClass 指定全局java处理类， fallback指定 使用类中哪个方法处理Java异常
            fallbackClass = CustomGlobalFallbackHandler.class, fallback = "fallbackHandlerMethod1",
            //exceptionsToIgnore 指定 fallback 不处理哪些异常
            exceptionsToIgnore = {NullPointerException.class}
    )
    public Result t6() {
        if ((++num) % 3==0) {
            throw new RuntimeException("runtime exception");
        }
        if ((++num) % 2==0) {
            throw new NullPointerException("null point exception");
        }
        return Result.success("t5()执行");
    }




    @GetMapping("/member/get/{id}")
    public Result getMemberById(@PathVariable("id") Long id) {
        //让线程休眠 1s, 模拟执行时间
//        try {
//            TimeUnit.MILLISECONDS.sleep(5000);
//        } catch (InterruptedException e) {
//            e.printStackTrace();
//        }
//        System.out.println("enter getMemberById... 当 前 线 程 id=" +
//                Thread.currentThread().getId() + " 时间=" + new Date());

        Member member = memberService.getMemberById(id);
        if (member != null) {
            return Result.success("查询用户成功 nacos 10004",member);
        }
        return Result.error("402","用户不存在");
    }

    @PostMapping("/member/save")
    public Result saveMember(@RequestBody Member member) {
        int affected = memberService.save(member);
        if (affected > 0) {
            return Result.success("添加用户成功",null);
        }
        return Result.error("401","添加用户失败");
    }
}
